← Back

CODE MODULARITY AND MODULES IN JAVASCRIPT

Code modularity means splitting code into separate files where each file is responsible for one part of the project.

This note explains code modularity and ECMAScript modules in simple language.

You will learn:

  1. what code modularity is
  2. why modules are useful
  3. what ECMAScript Modules are
  4. what default export and import mean
  5. what named export and import mean
  6. how renaming works
  7. what namespace import is
  8. how local images are imported in Vite projects

1. What is code modularity?

As a project grows, one file is no longer enough.

Developers split code into separate files, where each file is responsible for one part of the project. This is called code modularity.

A module is usually one JavaScript file that contains a specific piece of logic and can be used in other files.

Diagram 1. From one big file to modules

Big project
-> too much code in one file
-> split code into smaller files
-> each file handles one job

Instead of putting everything in one place, we divide the code into logical parts. That makes the project easier to understand.

2. Why modularity is useful

Modules have three main advantages:

Maintainability

A good module should depend as little as possible on other parts of the project.

This means:

Namespace

Global variables can create conflicts. If unrelated files use the same global names, problems appear.

Modules help avoid this because each module has its own scope.

Reusability

A module can be reused in different places or even in different projects.

This is better than copying old code again and again and editing it manually.

Diagram 2. Why modules are useful

Modules
|
|- easier to maintain
|- protect namespace
`- easier to reuse

This is the main reason modules are so important in modern JavaScript.

3. What are ECMAScript Modules?

ECMAScript Modules, or ESM, are the modern JavaScript module system.

They define a standard way to:

In simple words:

One file can share something
Another file can use it

Diagram 3. Main idea of ESM

Module A
-> exports value

Module B
-> imports value
-> uses that value

Modules communicate through export and import.

4. Module example

makeMessage.js

export default function makeMessage(username) {
  return `Welcome, ${username}!`;
}

index.js

import makeMessage from "./makeMessage";

console.log(makeMessage("Jacob")); // "Welcome, Jacob!"

This means:

Diagram 4. Module connection

makeMessage.js
-> exports function

index.js
-> imports function
-> calls function

5. Important idea about modules

Each JavaScript file works in its own module context.

That means:

Diagram 5. Each file is its own module

File 1
-> own module scope

File 2
-> own module scope

They connect only through import/export

This helps keep code organized and safer.

6. Default export

A module can have one default export.

This is usually the main value of the file.

The syntax is:

export default exportedValue

Example of default export

const makeMessage = username => {
  return `Welcome, ${username}!`;
};

export default makeMessage;

Here, makeMessage is the main thing exported from the file.

Diagram 6. Default export

One module
-> one main exported value
-> default export

Easy rule:

default export = the main thing from this file

7. Default import

To import a default export, use:

import name from "..."

Example

import makeMessage from "./makeMessage";

console.log(makeMessage("Jacob"));

Important detail: the imported name can be chosen freely.

So this also works:

import createMessage from "./makeMessage";

It still works because it is a default import.

Diagram 7. Default import

export default makeMessage
-> import anyName from "./makeMessage"

With default import, the local variable name is your choice.

8. Named export

A named export is used when a module exports one or more values with specific names.

Syntax:

export exportedValue

Example

export const makeMessage = username => {
  return `Welcome, ${username}!`;
};

export const levels = ["easy", "medium", "hard"];

Here the module exports:

Diagram 8. Named exports

One module
|
|- export makeMessage
`- export levels

Unlike default export, a module can have many named exports.

9. Named import

To import named exports, use curly braces:

import { name } from "..."

Example

import { makeMessage, levels } from "./makeMessage";

console.log(makeMessage("Jacob"));
console.log(levels);

Important rule: for named import, the names must match the exported names.

Diagram 9. Named import

Module exports:
makeMessage
levels

Import:
{ makeMessage, levels }

Easy rule:

named export = fixed name
named import = same name

10. Default export vs named export

This is one of the most important differences.

Default export

Named export

Diagram 10. Default vs named

Default export
-> one main value
-> import without {}

Named export
-> many values possible
-> import with {}

11. Renaming during import

Sometimes the imported name is too long, too general, or conflicts with a variable name in the current file.

Then you can rename it with:

import { name as newName } from "..."

Example

export const original = "Hello, World!";
import { original as renamed } from "./myModule.js";

console.log(renamed); // "Hello, World!"

Diagram 11. Renaming

Exported name:
original

Imported name:
renamed

The value stays the same. Only the local variable name changes.

12. When renaming is useful

Renaming is useful when:

Diagram 12. Why rename

Imported name problem
|
|- too general
|- too long
`- name conflict

Solution
-> use as

13. Namespace import

Namespace import means importing all named exports from a module as one object.

Syntax:

import * as everything from "..."

Example

export const name = "Mango";
export const age = 26;
export const email = "mango@mail.com";
import * as user from "./myModule.js";

console.log(user.name); // "Mango"
console.log(user.age); // 26
console.log(user.email); // "mango@mail.com"

Diagram 13. Namespace import

Module exports many named values
-> import * as user
-> all values become properties of user object

Now you access everything through dot notation.

14. Why namespace import is useful

Namespace import is useful when:

Diagram 14. Namespace import idea

Many exports
-> one namespace object
-> cleaner access with dot notation

15. Local images in Vite projects

In regular HTML, images are often used through relative paths.

But in projects built with bundlers like Vite, local images are usually imported as modules.

Why?

Because the bundler:

Diagram 15. Bundler and images

Local image in project
-> import image in JavaScript
-> bundler generates correct final path
-> use that path in src

This helps avoid path problems in builds and deployment.

16. Importing a local image

Example:

import catImage from "./images/cat.jpg";

Here:

Diagram 16. Image import flow

./images/cat.jpg
-> import

catImage
-> string with ready path

17. Why this image import method is useful

This approach helps:

Diagram 17. Why import images

Import image as module
-> safer paths
-> works with bundler
-> easy to use in JavaScript

18. Easy memory rules

Module = one JavaScript file with code

export = share something
import = use something from another file

default export = one main value
named export = one or more specific values

as = rename during import
* as = namespace import

Vite image import = local image becomes module path

19. Quick summary

20. Final conclusion

If you understand these ideas:

modularity
module
export
import
default export
named export
renaming
namespace import
image import in Vite

then you already have a strong foundation for working with modules in modern JavaScript.

Modules are one of the most important parts of real frontend development because they help keep projects clean, scalable, and easier to maintain.

← Back